/*********************************************************************************
 *      Copyright:  (C) huangxiangming<1732012962@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  proc.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(25/04/18)
 *         Author:  huangxiangming<1732012962@qq.com>
 *      ChangeLog:  1, Release initial version on "25/04/18 16:13:06"
 *                 
 ********************************************************************************/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <fcntl.h>

#include "proc.h"
#include "logger.h"

static int			size = 11;
int         		stop = 0;

//信号部分
//信号处理函数
void proc_signal_handler(int signum) 
{                 
	switch(signum)
	{             
		case SIGINT:			//ctr+c
			log_warn("SIGINT - stopping\n");
			stop = 1;
			break;

		case SIGTERM:			//kill
			log_warn("SIGTERM - stopping\n");
			stop = 1;
			break;

		case SIGPIPE:
			log_warn("SIGPIPE - warnning\n");
			break;

		default:
			break;
	}
}

void install_signal()
{
	struct sigaction 		sigact;
	    
	log_info("Install default signal handler.\n");
	        
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigact.sa_handler = proc_signal_handler;
	       
	sigaction(SIGINT, &sigact, 0); 
	sigaction(SIGTERM, &sigact, 0); 
	sigaction(SIGPIPE, &sigact, 0); 
} 


//后台
int set_background_running(int daemon_flag, char *pidfile)
{
	if ( !pidfile )
	{
		return 0;
	}

	if ( !check_background_running(pidfile) )
	{
		log_warn("Program alread running");
		return 0;
	}

	if ( daemon_flag )		//daemon_flag为1进入后台，0不进入
	{
		daemon(1, 1);
		log_info("Program running as daemon [PID: %d]\n", getpid());
	}

	if (record_daemon_pid(pidfile) < 0)
	{  
		log_error("Record PID to \"%s\" failure\n", pidfile);
		return 0;                                  
	}

	return 1;
}

int check_background_running(char *pidfile)
{
	pid_t				pid = -1;
	struct stat			fstatbuf;

	if ( !stat(pidfile, &fstatbuf) )
	{
		log_info("PID record file \"%s\" exist", pidfile);

		pid = get_daemon_pid(pidfile);
		if ( pid > 0 )
		{
			if ( !kill(pid, 0) )
			{
				log_error("Program with PID[%d] is running\n", pid);
				return 0;
			}
			
			log_debug("Program with PID[%d] has exited\n", pid);
			remove(pidfile);
			return 1;
		}

		if ( 0 == pid )
		{
			log_debug("Read program PID failure\n");	//atoi解析失败
			remove(pidfile);
			return 1;
		}

		log_error("Read record file failure", pidfile);
		return 0;
	}

	return 1;
}

pid_t get_daemon_pid(char *pidfile)
{
	pid_t			pid;
	FILE			*f;
	char			pid_ascii[size];

	f = fopen(pidfile, "rb");
	if ( f != NULL )
	{
		(void)fgets(pid_ascii, size, f);
		(void)fclose(f);
		pid = atoi(pid_ascii);
	}
	else
	{
		log_error("open PID record file failure\n");
		return -1;
	}
	return pid;
}

int record_daemon_pid(char *pidfile)
{
	struct stat 		fstatbuf;
	int					fd = -1;
	int 				mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
	char				ipc_dir[64] = {0};
	char				pid[size];

	strncpy(ipc_dir, pidfile, 64);

	dirname(ipc_dir);

	if ( stat(ipc_dir, &fstatbuf) < 0 )
	{
		if ( mkdir(ipc_dir, mode) < 0 )
		{
			log_error("create \"%s\" failure\n", ipc_dir);
			return -1;
		}

		(void)chmod(ipc_dir, mode);
	}

	mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
	fd = open(pidfile, O_RDWR|O_CREAT|O_TRUNC, mode);
	if ( fd < 0 )
	{
		log_error("create \"%s\" failure\n", pidfile);
		return -1;
	}

	snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid());
	write(fd, pid, strlen(pid));
	close(fd);
	
	return 0;
}

int stop_background_running(char *pidfile)
{
	pid_t            pid = -1;
	struct stat      fstatbuf;

	if ( stat(pidfile, &fstatbuf) < 0)
	{
		return 0;
	}
	 
	pid = get_daemon_pid(pidfile);
	if (pid > 0)
	{
		while ( (kill(pid, 0) ) == 0)
		{
			kill(pid, SIGTERM);
			sleep(1);
		}
		 
		remove(pidfile);
	}

	return 0;
}
		
